////////////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2008 Gabriel Montagné Láscaris-Comneno and Alberto
//  Brealey-Guzmán.
//
//  Permission is hereby granted, free of charge, to any person obtaining a
//  copy of this software and associated documentation files (the "Software"),
//  to deal in the Software without restriction, including without limitation
//  the rights to use, copy, modify, merge, publish, distribute, sublicense,
//  and/or sell copies of the Software, and to permit persons to whom the
//  Software is furnished to do so, subject to the following conditions:
//
//  The above copyright notice and this permission notice shall be included in
//  all copies or substantial portions of the Software.
//
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
//  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
//  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
//  DEALINGS IN THE SOFTWARE.
//
////////////////////////////////////////////////////////////////////////////////

package com.rojored.utils
{

import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;

/**
 *  The MathUtil class is an all-static class with a collection of useful math
 *  methods.
 */
public class MathUtil
{

    //--------------------------------------------------------------------------
    //
    //  Class methods
    //
    //--------------------------------------------------------------------------

    /**
     *  Return the largest rectangle with the same aspect ratio of the first
     *  argument that will fit into the second rectangle.
     */
    public static function fitRectangle(a:Rectangle, b:Rectangle):Rectangle
    {
        var aRatio:Number = a.width / a.height;
        var bRatio:Number = b.width / b.height;
        var scale:Number =
            aRatio < bRatio ?  b.height / a.height : b.width / a.width;

        var matrix:Matrix = new Matrix(scale, 0, 0, scale);
        var scaledBottomRight:Point =
            matrix.deltaTransformPoint(new Point(a.width ,a.height))
        return new Rectangle(0, 0, scaledBottomRight.x, scaledBottomRight.y);
    }

    /**
     *  Modulo implementation which always gives a result with the same sign
     *  as the divisor.
     *
     *  Where
     *  <pre>
     *  <code>-1 % 100 == -1</code>
     *  <code>modulo(-1, 100) == 99</code>
     *  </pre>
     */
    public static function modulo(a:int, n:int):int
    {
        return a - (n * Math.floor(a / n));
    }

    /**
     *  Return the closest value to origin in the values array.
     */
    public static function snap(origin:Number, values:Array):Number
    {
        if (!values || values.length < 1)
            return origin;

        var result:Number = values[0];
        var n:int = values.length;

        if (n == 1)
            return result;

        for (var i:int = 1; i < n; i++)
        {
            var value:Number = values[i];
            if (value == origin)
            {
                result = origin;
                break;
            }
            if (Math.abs(origin - result) > Math.abs(origin - value))
                result = value;
        }
        return result;
    }
    
    /**
     *  Return the average arithmetic mean from the provided number vector.
     */
    public static function arithmeticMean(numbers:Vector.<Number>):Number
    {
        var n:int = numbers.length;
        var sum:Number = 0;
        for (var i:int = 0; i < n; i++)
        {
            sum += numbers[i];
        }
        return sum / n;
    }
}
}
